/*-------------------------------------------------------------------------
 *
 * nbtdesc.c
 *	  访问/nbtree/nbtxlog.c 的 rmgr 描述例程
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/backend/access/rmgrdesc/nbtdesc.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "access/nbtxlog.h"

void btree_desc(StringInfo fc_buf, XLogReaderState *fc_record)
{
	char	   *fc_rec = XLogRecGetData(fc_record);
	uint8		fc_info = XLogRecGetInfo(fc_record) & ~XLR_INFO_MASK;

	switch (fc_info)
	{
		case XLOG_BTREE_INSERT_LEAF:
		case XLOG_BTREE_INSERT_UPPER:
		case XLOG_BTREE_INSERT_META:
		case XLOG_BTREE_INSERT_POST:
			{
				xl_btree_insert *fc_xlrec = (xl_btree_insert *) fc_rec;

				appendStringInfo(fc_buf, "off %u", fc_xlrec->offnum);
				break;
			}
		case XLOG_BTREE_SPLIT_L:
		case XLOG_BTREE_SPLIT_R:
			{
				xl_btree_split *fc_xlrec = (xl_btree_split *) fc_rec;

				appendStringInfo(fc_buf, "level %u, firstrightoff %d, newitemoff %d, postingoff %d",
								 fc_xlrec->level, fc_xlrec->firstrightoff,
								 fc_xlrec->newitemoff, fc_xlrec->postingoff);
				break;
			}
		case XLOG_BTREE_DEDUP:
			{
				xl_btree_dedup *fc_xlrec = (xl_btree_dedup *) fc_rec;

				appendStringInfo(fc_buf, "nintervals %u", fc_xlrec->nintervals);
				break;
			}
		case XLOG_BTREE_VACUUM:
			{
				xl_btree_vacuum *fc_xlrec = (xl_btree_vacuum *) fc_rec;

				appendStringInfo(fc_buf, "ndeleted %u; nupdated %u",
								 fc_xlrec->ndeleted, fc_xlrec->nupdated);
				break;
			}
		case XLOG_BTREE_DELETE:
			{
				xl_btree_delete *fc_xlrec = (xl_btree_delete *) fc_rec;

				appendStringInfo(fc_buf, "latestRemovedXid %u; ndeleted %u; nupdated %u",
								 fc_xlrec->latestRemovedXid, fc_xlrec->ndeleted, fc_xlrec->nupdated);
				break;
			}
		case XLOG_BTREE_MARK_PAGE_HALFDEAD:
			{
				xl_btree_mark_page_halfdead *fc_xlrec = (xl_btree_mark_page_halfdead *) fc_rec;

				appendStringInfo(fc_buf, "topparent %u; leaf %u; left %u; right %u",
								 fc_xlrec->topparent, fc_xlrec->leafblk, fc_xlrec->leftblk, fc_xlrec->rightblk);
				break;
			}
		case XLOG_BTREE_UNLINK_PAGE_META:
		case XLOG_BTREE_UNLINK_PAGE:
			{
				xl_btree_unlink_page *fc_xlrec = (xl_btree_unlink_page *) fc_rec;

				appendStringInfo(fc_buf, "left %u; right %u; level %u; safexid %u:%u; ",
								 fc_xlrec->leftsib, fc_xlrec->rightsib, fc_xlrec->level,
								 EpochFromFullTransactionId(fc_xlrec->safexid),
								 XidFromFullTransactionId(fc_xlrec->safexid));
				appendStringInfo(fc_buf, "leafleft %u; leafright %u; leaftopparent %u",
								 fc_xlrec->leafleftsib, fc_xlrec->leafrightsib,
								 fc_xlrec->leaftopparent);
				break;
			}
		case XLOG_BTREE_NEWROOT:
			{
				xl_btree_newroot *fc_xlrec = (xl_btree_newroot *) fc_rec;

				appendStringInfo(fc_buf, "lev %u", fc_xlrec->level);
				break;
			}
		case XLOG_BTREE_REUSE_PAGE:
			{
				xl_btree_reuse_page *fc_xlrec = (xl_btree_reuse_page *) fc_rec;

				appendStringInfo(fc_buf, "rel %u/%u/%u; latestRemovedXid %u:%u",
								 fc_xlrec->node.spcNode, fc_xlrec->node.dbNode,
								 fc_xlrec->node.relNode,
								 EpochFromFullTransactionId(fc_xlrec->latestRemovedFullXid),
								 XidFromFullTransactionId(fc_xlrec->latestRemovedFullXid));
				break;
			}
		case XLOG_BTREE_META_CLEANUP:
			{
				xl_btree_metadata *fc_xlrec;

				fc_xlrec = (xl_btree_metadata *) XLogRecGetBlockData(fc_record, 0,
																  NULL);
				appendStringInfo(fc_buf, "last_cleanup_num_delpages %u",
								 fc_xlrec->last_cleanup_num_delpages);
				break;
			}
	}
}

const char * btree_identify(uint8 fc_info)
{
	const char *fc_id = NULL;

	switch (fc_info & ~XLR_INFO_MASK)
	{
		case XLOG_BTREE_INSERT_LEAF:
			fc_id = "INSERT_LEAF";
			break;
		case XLOG_BTREE_INSERT_UPPER:
			fc_id = "INSERT_UPPER";
			break;
		case XLOG_BTREE_INSERT_META:
			fc_id = "INSERT_META";
			break;
		case XLOG_BTREE_SPLIT_L:
			fc_id = "SPLIT_L";
			break;
		case XLOG_BTREE_SPLIT_R:
			fc_id = "SPLIT_R";
			break;
		case XLOG_BTREE_INSERT_POST:
			fc_id = "INSERT_POST";
			break;
		case XLOG_BTREE_DEDUP:
			fc_id = "DEDUP";
			break;
		case XLOG_BTREE_VACUUM:
			fc_id = "VACUUM";
			break;
		case XLOG_BTREE_DELETE:
			fc_id = "DELETE";
			break;
		case XLOG_BTREE_MARK_PAGE_HALFDEAD:
			fc_id = "MARK_PAGE_HALFDEAD";
			break;
		case XLOG_BTREE_UNLINK_PAGE:
			fc_id = "UNLINK_PAGE";
			break;
		case XLOG_BTREE_UNLINK_PAGE_META:
			fc_id = "UNLINK_PAGE_META";
			break;
		case XLOG_BTREE_NEWROOT:
			fc_id = "NEWROOT";
			break;
		case XLOG_BTREE_REUSE_PAGE:
			fc_id = "REUSE_PAGE";
			break;
		case XLOG_BTREE_META_CLEANUP:
			fc_id = "META_CLEANUP";
			break;
	}

	return fc_id;
}
